作者:陈广
日期:2018-4-9
拼数字游戏是在我的《C#程序设计基础教程与实训》这本书里数组这一章的一个例子,代码很精简。现在学 JavaScript,正好拿这个程序来练手。这一系列文章讲的是 TypeScript,就用一个 JavaScript 例子作为开头吧。先上效果再写代码。
玩游戏的时候需要注意,有一半的机会游戏是无法完成的,关于这一点在我的《数据结构 C#语言描述》这本书有详细描述和算法解决办法。此程序只是演示元素的动态创建,就不写那么周全了。
新建一个文件夹,命名为NumberGame,点右键用 vscode 打开。然后新建一个NumberGame.html文件。输入如下代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>拼数字游戏</title>
<link rel="stylesheet" href="NumberGame.css">
</head>
<body>
<div id="Container"></div>
<button id="Button">开始游戏</button>
</body>
<script src="NumberGame.js"></script>
</html>
这里只有一个 div 和一个 button,九宫格本来应该有九个按钮,可以直接在 div 里写 HTML 创建。但是为了学习 JavaScript,这次使用 JavaScript 动态创建按钮并关联事件,包括 button 的事件。其实即使使用 JavaScript 动态创建,也有两种方式。第一种是使用 JavaScript 函数创建,这次准备使用这种方法创建。第二种是在 JavaScript 中拼揍 HTML 然后加到 div 中。这种方式准备在用 TypeScript 重写的时候使用。
新建一个NumberGame.css文件,使用如下代码:
body {
text-align: center;
background-color: #bbb;
}
#Container {
position: relative;
width: 240px;
height: 240px;
margin: 0 auto;
margin-top: 20px;
border: 5px solid darkgoldenrod;
border-radius: 5px;
}
.NumBtn {
position: absolute;
background-color: tomato;
color: azure;
box-sizing: border-box;
border: 1px solid #ccc;
font-size: 50px;
user-select: none;
}
#Button {
margin-top: 20px;
padding: 10px 20px;
background: #A2B598;
background: -webkit-gradient(linear, left top, left bottom, from(#BDD1B4), to(#A2B598));
background: -moz-linear-gradient(-90deg, #BDD1B4, #A2B598);
filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr='#BDD1B4', EndColorStr='#A2B598');
}
#Button:hover {
background: #BDD1B4;
background: -webkit-gradient(linear, left top, left bottom, from(#A2B598), to(#BDD1B4));
background: -moz-linear-gradient(-90deg, #A2B598, #BDD1B4);
filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr='#A2B598', EndColorStr='#BDD1B4');
}
#Button:active {
background: #A2B598;
}
css不是我关注的重点,所以按钮随便上网找了个 CSS 套上去收工。这里我就不讲了。
新建一个NumberGame.js文件,使用如下代码:
//全局变量
var btnArr = new Array(3); //装按钮的数组
var unRow = 0;
var unCol = 0;
//窗体载入事件
window.onload = function () {
for (var i = 0; i < btnArr.length; i++) {
btnArr[i] = new Array(3);
}
Create_div();
//给开始游戏按钮绑定事件
document.getElementById("Button").addEventListener("click", PlayGame);
}
function Create_div() {
var container = document.getElementById("Container");
for (var i = 0; i < 9; i++) {
var btn = document.createElement("button"); //创建装数字的Div
btn.className = "NumBtn";
//设置数字div边长
var edgeLen = Math.floor((container.offsetWidth - 10) / 3);
btn.style.height = edgeLen + "px";
btn.style.width = edgeLen + "px";
//设置数字div位置
btn.style.left = (i % 3) * edgeLen + "px";
btn.style.top = Math.floor(i / 3) * edgeLen + "px";
btn.innerText = i + 1; //设置文本
btn.style.lineHeight = edgeLen + "px"; //垂直居中
//给每个加入div的按钮绑定事件
btn.addEventListener("click", Btn_Click);
container.appendChild(btn); //将按钮加入 div
//加入数组
btnArr[Math.floor(i / 3)][i % 3] = btn;
}
}
//随机函数low表示最小随机值,high表示最大随机值
function randomBetween(low, high) {
return Math.floor(Math.random() * (high - low + 1) + low);
}
//开始游戏方法,用于绑定开始游戏按钮
function PlayGame() {
btnArr[unRow][unCol].style.display = "block";
var nums = [1, 2, 3, 4, 5, 6, 7, 8, 9];
for (var i = 0; i < 8; i++) {
var rmNum = randomBetween(i, 8);
var temp = nums[i];
nums[i] = nums[rmNum];
nums[rmNum] = temp;
}
for (var i = 0; i < 9; i++) {
btnArr[Math.floor(i / 3)][i % 3].innerText = nums[i];
}
var cover = randomBetween(0, 8);
unRow = Math.floor(cover / 3);
unCol = cover % 3;
btnArr[unRow][unCol].style.display = "none";
}
//单击数字时的事件
function Btn_Click() {
var row = this.offsetTop / 80;
var col = this.offsetLeft / 80;
if (Math.abs(row - unRow) + Math.abs(col - unCol) == 1) {
var temp = btnArr[unRow][unCol].innerText;
btnArr[unRow][unCol].innerText = btnArr[row][col].innerText
btnArr[row][col].innerText = temp;
btnArr[unRow][unCol].style.display = "block";
btnArr[row][col].style.display = "none";
unRow = row;
unCol = col;
}
//判定是否游戏结束
for (var i = 0; i < 9; i++) {
if (btnArr[Math.floor(i / 3)][i % 3].innerText != i + 1) {
break;
}
if (i == 8) {
btnArr[unRow][unCol].style.display = "block";
alert("闯关成功!");
}
}
}
这段代码主要演示了如何使用 JavaScript 动态加载 HTML 元素并绑定事件。关键点在于:
createElement
创建一个 HTML 元素addEventListener
给一个 HTML 元素绑定一个事件appendChild
给 div 加入一个子元素JavaScript 不支持二维数组,坑爹。好在可以模拟,这里也做了演示。算法这一块我就不讲了,不重点。